package mk.jug.academy.controller;

import java.util.logging.Logger;

import mk.jug.academy.model.Lecturer;
import mk.jug.academy.model.Page;
import mk.jug.academy.model.Student;
import mk.jug.academy.model.StudentReview;
import mk.jug.academy.model.User;
import mk.jug.academy.service.LecturerService;
import mk.jug.academy.service.StudentReviewService;
import mk.jug.academy.service.StudentService;
import mk.jug.academy.util.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.google.appengine.api.memcache.MemcacheService;

/**
 * View layer coordinator of the backend student review functionality.
 *
 * @author Ice.Penov
 */
@Controller
public class ReviewAdminController extends BaseController {
			
	private static final Logger LOG = Logger.getLogger(ReviewAdminController.class.getName());
	//TODO: Externalize this.
	public static final int ITEMS_PER_PAGE = 8;
	
	@Autowired private StudentReviewService studentReviewService;
	@Autowired private StudentService studentService;
	@Autowired private LecturerService lecturerService;
	@Autowired private MemcacheService memcacheService;
	
	private static String LIST_IN_PROGRESS = "admin.reviews.inprogress";
	private static String UPDATE_REVIEW = "admin.reviews.update";
	private static String LIST_COMPLETED = "admin.reviews.completed";
	private static String LIST_DELETED = "admin.reviews.deleted";
	private static String VIEW_REVIEW = "admin.reviews.view";
	
	@RequestMapping("/admin/reviews/inprogress.do")
	public String inProgress(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<StudentReview> pagedReviews = studentReviewService.listCurrentlyDefined(page, ITEMS_PER_PAGE);
				map.addAttribute("reviews", pagedReviews.getItems());
				map.addAttribute("pages", Utils.getPageNumber(ITEMS_PER_PAGE, pagedReviews.getTotalCount()));
				map.addAttribute("page", page);
				return LIST_IN_PROGRESS;
			}
		}.result();
	}
	
	@RequestMapping("/admin/reviews/start.do")
	public String start(final ModelMap map, final @RequestParam("studentID") Long studentID) {
		return new ControllerContext(map) {
			public String execute() {
				Student student = studentService.load(studentID);
				String email = SecurityContextHolder.getContext().getAuthentication().getName();
				User user = (User) memcacheService.get(email);
				Lecturer lecturer = lecturerService.load(user.getId());
				StudentReview review = new StudentReview();
				studentReviewService.startReview(student, lecturer, review);
				LOG.fine("Review for student [" + Student.CODE_PREFIX + "-" + review.getStudentID() + "] has been started.");				
				return "redirect:/admin/reviews/inprogress.do";
			}
		}.result();
	}
	
	@RequestMapping("/admin/reviews/update.do")
	public String updateReview(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				StudentReview review = studentReviewService.load(id);
				map.addAttribute("review", review);
				return UPDATE_REVIEW;
			}
		}.result();
	}
	
	@RequestMapping(value = "/admin/reviews/saveReview.do", method = RequestMethod.POST)
	public String saveReview(final ModelMap map, final @ModelAttribute("review") StudentReview changed, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				StudentReview review = studentReviewService.load(id);
				review.setReview(changed.getReview());
				LOG.fine("Review for student [" + Student.CODE_PREFIX + "-" + review.getStudentID() + "] has been modified.");
				studentReviewService.continueReview(review);
				return "redirect:/admin/reviews/inprogress.do";
			}
		}.result();
	}
	
	@RequestMapping(value = "/admin/reviews/complete.do")
	public String completeReview(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				StudentReview review = studentReviewService.load(id);
				studentReviewService.completeReview(review);
				return "redirect:/admin/reviews/inprogress.do";
			}
		}.result();
	}
	
	@RequestMapping(value = "/admin/reviews/delete.do")
	public String delete(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				StudentReview review = studentReviewService.load(id);
				studentReviewService.deleteReview(review);
				return "redirect:/admin/reviews/inprogress.do";
			}
		}.result();
	}
	
	@RequestMapping("/admin/reviews/completed.do")
	public String completed(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<StudentReview> pagedReviews = studentReviewService.listCompleted(page, ITEMS_PER_PAGE);
				map.addAttribute("reviews", pagedReviews.getItems());
				map.addAttribute("pages", Utils.getPageNumber(ITEMS_PER_PAGE, pagedReviews.getTotalCount()));
				map.addAttribute("page", page);
				return LIST_COMPLETED;
			}
		}.result();
	}
	
	@RequestMapping("/admin/reviews/view.do")
	public String view(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				StudentReview review = studentReviewService.load(id);
				map.addAttribute("review", review);
				return VIEW_REVIEW;
			}
		}.result();
	}
	
	@RequestMapping("/admin/reviews/deleted.do")
	public String deleted(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<StudentReview> pagedReviews = studentReviewService.listDeleted(page, ITEMS_PER_PAGE);
				map.addAttribute("reviews", pagedReviews.getItems());
				map.addAttribute("pages", Utils.getPageNumber(ITEMS_PER_PAGE, pagedReviews.getTotalCount()));
				map.addAttribute("page", page);
				return LIST_DELETED;
			}
		}.result();
	}

}